package com.game.render
{
	import com.game.events.GameEvent;
	import com.game.events.GameEventDispatcher;
	import com.game.events.GameEventType;
	
	import flash.display.DisplayObjectContainer;

	public class RenderManager
	{
		/**
		 * 容器
		 */
		protected var container : DisplayObjectContainer;

		/**
		 * 显示列表
		 */
		protected var renderList : Array = [];

		/**
		 * 事件管理器
		 */
		protected var notify : GameEventDispatcher;

		private static var instance : RenderManager;

		public function RenderManager(container : DisplayObjectContainer)
		{
			if (instance)
			{
				throw new Error("单例错误" + this);
			}
			this.container = container;
			notify = GameEventDispatcher.getInstance();
			notify.addEventListener(GameEventType.ADD_GAME_RENDER, addRender)
			notify.addEventListener(GameEventType.DEL_GAME_RENDER, removeRender);
			notify.addEventListener(GameEventType.UPDATE_RANDER_INDEX, checkAddRender);
		}

		public static function getInstance(container : DisplayObjectContainer = null) : RenderManager
		{
			if (instance == null)
			{
				instance = new RenderManager(container);
			}
			return instance;
		}

		public function get length() : int
		{
			return renderList.length;
		}

		/**
		 * 添加渲染对象
		 * @param render
		 * @return
		 *
		 */
		public function addRender(evt : GameEvent) : Boolean
		{
			var render : RenderData = evt.body;

			if (render == null)
				return false;

			if (renderList.indexOf(render) == -1)
			{
				var index : int = renderList.push(render);
				addToContainer(render, index);
				return true;
			}
			return false;
		}

		/**
		 * 移除渲染对象
		 * @param render
		 * @return
		 *
		 */
		public function removeRender(evt : GameEvent) : Boolean
		{
			var render : RenderData = evt.body;

			if (render == null)
				return false;
			var index : int = renderList.indexOf(render);
			removeFromContainer(render);

			if (index != -1)
			{
				renderList.splice(index, 1);
				return true;
			}
			return false;
		}

		/**
		 * 检测如果渲染对象新增的子级是否需要添加到显示列表
		 * @param render
		 *
		 */
		public function checkAddRender(evt : GameEvent) : void
		{
			var render : RenderData = evt.body;

			if (render == null)
				return;

			var index : int = -1;

			if (render.render && render.render.parent)
			{
				index = container.getChildIndex(render.render);
			}

			if (index == -1)
				return;
			var len : int = render.numChildren;
			var child : RenderData;
			var i : int

			for (i = 0; i < len; i += 1)
			{
				child = render.getChildAt(i);

				if (child != null)
					index = addToContainer(child, index);
			}
		}

		/**
		 * 更新渲染列表.按照x,y深度排序
		 * @param elapsedTime
		 *
		 */
		public function update(elapsedTime : uint) : void
		{
			updateChildIndexs();
		}

		protected function updateChildIndexs() : void
		{
			renderList.sortOn(["zIndex", "id"], [Array.NUMERIC, Array.DESCENDING | Array.NUMERIC]);

			var render : RenderData;
			var i : int = 0;

			for each (render in renderList)
			{
				i = updateRenderIndex(render, i);
			}
		}

		private function updateRenderIndex(render : RenderData, index : int) : int
		{
			if (render.render && render.render.parent)
			{
				if (index >= container.numChildren) //防止溢出
					index = container.numChildren - 1;
				render.render.parent.setChildIndex(render.render, index++);
			}

			var len : int = render.numChildren;
			var child : RenderData;
			var i : int;

			for (i = 0; i < len; i += 1)
			{
				child = render.getChildAt(i);

				if (child)
					index = updateRenderIndex(child, index);
			}
			return index;
		}

		/**
		 * 添加渲染对象,和它的子类对象,到场景中
		 * @param render
		 * @param index
		 * @return
		 *
		 */
		private function addToContainer(render : RenderData, index : int) : int
		{
			if (render.render) //如果指定为不需要添加到渲染列表
			{
				if (index > container.numChildren) //防止超出范围
					index = container.numChildren;
				container.addChildAt(render.render, index++);
			}

			var len : int = render.numChildren;
			var child : RenderData;
			var i : int;

			for (i = 0; i < len; i++)
			{
				child = render.getChildAt(i);

				if (child != null)
					index = addToContainer(child, index);
			}
			return index;
		}

		public function removeFromContainer(render : RenderData) : void
		{
			if (render.render && render.render.parent != null)
			{
				render.render.parent.removeChild(render.render);
			}

			var len : int = render.numChildren;
			var child : RenderData;
			var i : int;

			for (i = len - 1; i >= 0; i--)
			{
				child = render.getChildAt(i);

				if (child != null)
					removeFromContainer(child);
			}
		}

		/**
		 * 销毁
		 *
		 */
		public function destroy() : void
		{
			while (container.numChildren > 0)
			{
				container.removeChildAt(0);
			}
			renderList.length = 0;
			super.destroy();
		}
	}
}